숫자 컬럼 언더플로우 — FLOAT 대신 DOUBLE + TRUNC

NOTE

누적/차감 계산에 쓰이는 숫자 컬럼이 FLOAT일 때 발생할 수 있는 언더플로우(음수 오표기) 문제와 DOUBLE + 소수점 절삭(TRUNC)으로 보정하는 방법. 실무(IoT 계측값 누적 처리)에서 추출·일반화.

문제

IoT 장비 등에서 전달받은 계측값을 특정 배율로 나누어 저장하는 컬럼이 FLOAT 타입이면, 반복적인 나눗셈·누적 연산 과정에서 부동소수점 정밀도 한계로 인해 의도치 않은 언더플로우(값이 미세하게 음수로 표기) 가 발생할 수 있다.

-- 문제 재현 예시: FLOAT 컬럼에 나눗셈 결과를 반복 저장
-- 배율 나눗셈(예: 원시값/1000) 과정에서 이진 부동소수점 표현 오차 누적

원인은 두 가지로 좁혀 볼 수 있다.

  1. FLOAT(단정밀도, 4바이트)은 유효자릿수가 적어 반복 연산에서 오차가 누적되기 쉽다.
  2. 장비 자체가 특정 조건에서 0 또는 비정상 값을 보내는 경우(데이터 소스 자체의 이슈) — 이 경우는 DB 타입과 무관하므로 수신 측 값 검증도 함께 확인해야 한다.

해결

  1. FLOATDOUBLE(배정밀도, 8바이트)로 컬럼 타입 변경 — 유효자릿수를 늘려 오차 누적을 줄인다.
  2. 나눗셈 결과를 저장 전에 TRUNC(또는 ROUND)로 소수점 자릿수를 명시적으로 절삭한다. 부동소수점 오차가 남아있는 하위 자릿수를 저장 시점에 잘라내 언더플로우/오버플로우 표기 가능성을 낮춘다.
ALTER TABLE my_table MODIFY value_col DOUBLE;
 
-- 나눗셈 결과를 그대로 저장하지 않고, 소수점 자릿수를 명시적으로 절삭
-- 예: 원시값을 배율로 나눈 뒤 소수점 4자리까지만 절삭해 저장
-- INSERT ... VALUES ( ..., TRUNC(#{rawValue} / #{scale}, 4) )

일반화 — 언제 이 패턴을 적용하는가

  • 계측값·통화·비율처럼 반복적으로 나누거나 누적하는 숫자 컬럼에는 처음부터 FLOAT을 피하고 DOUBLE이나 DECIMAL(정확한 소수 연산이 필요하면 이쪽이 더 안전)을 기본으로 고려한다.
  • 이미 FLOAT으로 운영 중인 컬럼에서 음수/비정상 값이 간헐적으로 관측되면, “타입 정밀도 한계”와 “데이터 소스 자체 이상”을 함께 의심하고 둘 다 점검한다.
  • 저장 직전에 TRUNC/ROUND로 자릿수를 고정하면, 이후 조회·집계 시 미세한 오차가 눈덩이처럼 불어나는 것을 막을 수 있다.